////////////////////////////////////
// Win32WrapperClass			  //
//                                //
// File: PortScannerWindow.h      // 
// Desc: Definition of the        //
//			PortScannerWindow     //
//			class.				  //
////////////////////////////////////


#include "PortScannerWindow.h"
#include <stdio.h>
#include <commctrl.h>
#include <windowsx.h>

//////////////////////////////////////////////
// AboutDlgProc
//////////////////////////////////////////////

BOOL CALLBACK AboutDlgProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
	switch(Message)
	{
	case WM_INITDIALOG:
		// Get the desktop window's client rect
		HWND desktopHWND;
		desktopHWND = GetDesktopWindow();
		RECT desktopRect;
		GetClientRect(desktopHWND,&desktopRect);

		// Move the dialog to a position above and to the left of the bottom right corner of the screen
		MoveWindow(hwnd, desktopRect.right-450, desktopRect.bottom-325, 380, 255, TRUE);

		return TRUE;
	case WM_COMMAND:
		switch(LOWORD(wParam))
		{
		case IDOK:
			EndDialog(hwnd, IDOK);
			break;
		}
		break;
	case WM_LBUTTONDOWN:
		/*
		POINT pt;
		RECT rectStatic,rectImage;

		GetCursorPos(&pt);
		GetWindowRect(GetDlgItem(hwnd,IDC_GLOWDOTURL),  &rectStatic);
		GetWindowRect(GetDlgItem(hwnd,IDI_GDLOGOIMAGE), &rectImage);

		if (PtInRect(&rectStatic, pt) || PtInRect(&rectImage, pt)) {
			ShellExecute(NULL, "open", "http://www.glowdot.com", NULL, NULL, SW_SHOWNORMAL);
		} else {
			SendMessage(hwnd, WM_NCLBUTTONDOWN, HTCAPTION,NULL);
		}
		return TRUE;
	case WM_CTLCOLORSTATIC:
		// Set the color of the text for our URL
		if ((HWND)lParam == GetDlgItem(hwnd,IDC_GLOWDOTURL)) {
			// we're about to draw the static
			// set the text color in (HDC)lParam
			SetBkMode((HDC)wParam,TRANSPARENT);
			SetTextColor((HDC)wParam, RGB(0,0,255));
			return (BOOL)CreateSolidBrush (GetSysColor(COLOR_MENU));
		}
		return TRUE;
	case WM_SETCURSOR:
		POINT pt2;
		RECT rectStatic2,rectImage2;

		GetCursorPos(&pt2);
		GetWindowRect(GetDlgItem(hwnd,IDC_GLOWDOTURL),  &rectStatic2);
		GetWindowRect(GetDlgItem(hwnd,IDI_GDLOGOIMAGE), &rectImage2);

		if (PtInRect(&rectStatic2, pt2) || PtInRect(&rectImage2, pt2)) {
			SetCursor(LoadCursor(NULL,IDC_HAND));
		} else {
			SetCursor(LoadCursor(NULL,IDC_ARROW));
		}
		*/
		SendMessage(hwnd,WM_NCLBUTTONDOWN,HTCAPTION,NULL);
		return TRUE;
		break;
	default:
		return FALSE;
	}
	return TRUE;
}


///////////////////////////////////////////////
// PortScannerWindow::PortScannerWindow
///////////////////////////////////////////////
PortScannerWindow::PortScannerWindow(char *ClassName, char *WindowTitle, DWORD dwStyles, RECT *rect, HMENU hMenu, HINSTANCE hInstance) {
	m_pClassName	= ClassName;
	m_pWindowTitle	= WindowTitle;
	m_pRect			= rect;
	m_hInstance		= hInstance;
	m_dwStyles		= dwStyles;

	RECT desktopRect;
	GetWindowRect(GetDesktopWindow(),&desktopRect);

	int wWidth	=	m_pRect->right	-	m_pRect->left;
	int wHeight	=	m_pRect->bottom	-	m_pRect->top;

	m_pRect->left	=	((desktopRect.right		-	desktopRect.left)	-	wWidth)		/2;
	m_pRect->right	=	((desktopRect.right		-	desktopRect.left)	+	wWidth)		/2;
	m_pRect->top	=	((desktopRect.bottom	-	desktopRect.top)	-	wHeight)	/2;
	m_pRect->bottom	=	((desktopRect.bottom	-	desktopRect.top)	+	wHeight)	/2;

	// Initialize scanning flag
	m_bScanFlag = FALSE;

	// Assign our HMENU handle to the menu passed to the constructor
	m_hMenu = hMenu;

	// Initialize skinned flag
	m_bSkinned = FALSE;

	// Initialize display flags
	m_bShowOpen		= TRUE;
	m_bShowClosed	= TRUE;

	// Set our checkable menu options to checked initially
	CheckMenuItem(m_hMenu, ID_OUTPUT_SHOWOPEN, MF_CHECKED);
	CheckMenuItem(m_hMenu, ID_OUTPUT_SHOWCLOSED, MF_CHECKED);

}

///////////////////////////////////////////////
// PortScannerWindow::~PortScannerWindow
///////////////////////////////////////////////

PortScannerWindow::~PortScannerWindow () {

	// Destroy the render window
	if ( m_hWnd ) DestroyWindow( m_hWnd );
	m_hWnd = NULL;
}


///////////////////////////////////////////////
// PortScannerWindow::getHWND()
///////////////////////////////////////////////
HWND PortScannerWindow::getHWND() {
	return m_hWnd;
}

///////////////////////////////////////////////
// PortScannerWindow::BuildGUI()
///////////////////////////////////////////////

void PortScannerWindow::BuildGUI() {

	// Create and show our edit boxes
	m_hIPAddressEdit = CreateWindow("EDIT", "127.0.0.1", WS_VISIBLE | WS_CHILD | ES_LEFT | WS_BORDER | WS_TABSTOP | WS_GROUP | ES_AUTOHSCROLL, 30, 25, 120, 20, m_hWnd, 
		(HMENU)IDE_IPADDRESS, m_hInstance, NULL);	
	m_hStartPortEdit = CreateWindow("EDIT", "1", WS_VISIBLE | WS_CHILD | ES_NUMBER | WS_BORDER | WS_TABSTOP, 160, 25, 100, 20, m_hWnd, 
		(HMENU)IDE_STARTPORT, m_hInstance, NULL);	
	m_hEndPortEdit = CreateWindow("EDIT", "100", WS_VISIBLE | WS_CHILD | ES_NUMBER | WS_BORDER | WS_TABSTOP, 270, 25, 100, 20, m_hWnd, 
		(HMENU)IDE_ENDPORT, m_hInstance, NULL);	

	// Create and show our scan button
	m_hGoButton = CreateWindow("BUTTON", "Scan", WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON | WS_TABSTOP, 380, 25, 80, 20, m_hWnd, 
		(HMENU)IDB_GOSCAN, m_hInstance, NULL);

	// Create and show our labels
	// m_hIPAddressLabel = CreateWindow("STATIC", "IP Address", WS_VISIBLE | WS_CHILD, 10, 40, 120, 20, m_hWnd, 
	//	(HMENU)IDS_IPADDRESS, m_hInstance, NULL);	
	// m_hStartPortLabel = CreateWindow("STATIC", "Start Port", WS_VISIBLE | WS_CHILD | SS_LEFT, 140, 40, 100, 20, m_hWnd, 
	//	(HMENU)IDS_STARTPORT, m_hInstance, NULL);	
	// m_hEndPortLabel = CreateWindow("STATIC", "End Port", WS_VISIBLE | WS_CHILD, 250, 40, 100, 20, m_hWnd, 
	//	(HMENU)IDS_ENDPORT, m_hInstance, NULL);	

	// Create and show our text output area
	m_hDisplayArea = CreateWindow("EDIT", "Port Scanner v1.0\r\nby Rutger Storm\r\n\r\n", WS_VISIBLE | WS_CHILD | WS_BORDER | ES_MULTILINE
		| ES_AUTOVSCROLL | WS_VSCROLL | ES_READONLY, 10, 100, 470, 340, m_hWnd, (HMENU)IDT_OUTPUT, m_hInstance, NULL);

	// Create our GroupBoxes
	m_hOutputGroup = CreateWindow("BUTTON","Output",WS_VISIBLE | WS_CHILD | BS_GROUPBOX,5,75,480,370, m_hWnd, 
		(HMENU)IDB_OUTPUTGROUP, m_hInstance, NULL);
	m_hEditGroup   = CreateWindow("BUTTON","Settings",WS_VISIBLE | WS_CHILD | BS_GROUPBOX,5,5,480,60, m_hWnd, 
		(HMENU)IDB_SETTINGSGROUP, m_hInstance, NULL);

	// Create our close button hidden
	m_hCloseButton = CreateWindow("BUTTON", "X", WS_CHILD | BS_PUSHBUTTON | WS_TABSTOP, 480, 2, 12, 12, m_hWnd,
		(HMENU)IDB_CLOSEWINDOW, m_hInstance, NULL);		

	// Create our unskin button hidden
	m_hUnskinButton = CreateWindow("BUTTON", "Unskin", WS_CHILD | BS_PUSHBUTTON | BS_ICON | WS_TABSTOP, 15, 425, 32, 32, m_hWnd, 
		(HMENU)IDB_UNSKIN, m_hInstance, NULL);
	SendDlgItemMessage(m_hWnd, IDB_UNSKIN,  BM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)LoadIcon(m_hInstance, MAKEINTRESOURCE(IDI_ICON2)));

	// Create our show open/closed checkboxes for skinned mode
	m_hShowOpenCheckBx = CreateWindow("BUTTON","", WS_CHILD | BS_CHECKBOX | WS_TABSTOP, 95, 470, 15, 15, m_hWnd, 
		(HMENU)IDB_SHOWOPENCHKBX, m_hInstance, NULL);
	m_hShowClosedCheckBx = CreateWindow("BUTTON","", WS_CHILD | BS_CHECKBOX | WS_TABSTOP, 175, 470, 15, 15, m_hWnd, 
		(HMENU)IDB_SHOWCLOSEDCHKBX, m_hInstance, NULL);

	// Initialize checkboxes to checked
	SendMessage(m_hShowOpenCheckBx,BM_SETCHECK,BST_CHECKED,0);
	SendMessage(m_hShowClosedCheckBx,BM_SETCHECK,BST_CHECKED,0);

	// Create the tooltip for the unskin button	
	INITCOMMONCONTROLSEX iccex; 

	// Build tooltip for unskin button
	unsigned int uid = 0;       // for ti initialization
	char strTT[30] = "Switch To Unskinned Mode";
	LPTSTR lptstr = strTT;
	RECT rect;                  // for client area coordinates

	// INITIALIZE COMMON CONTROLS
	iccex.dwICC = ICC_WIN95_CLASSES;
	iccex.dwSize = sizeof(INITCOMMONCONTROLSEX);
	InitCommonControlsEx(&iccex);

	// CREATE A TOOLTIP WINDOW
	m_hUnskinButtonTT = CreateWindowEx(WS_EX_TOPMOST,
		TOOLTIPS_CLASS,
		NULL,
		WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,		
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		m_hUnskinButton,
		NULL,
		m_hInstance,
		NULL
		);

	SetWindowPos(m_hUnskinButtonTT,
		HWND_TOPMOST,
		0,
		0,
		0,
		0,
		SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);

	// GET COORDINATES OF THE MAIN CLIENT AREA
	GetClientRect (m_hUnskinButton, &rect);

	// struct specifying info about tool in ToolTip control
	TOOLINFO ti;

	// INITIALIZE MEMBERS OF THE TOOLINFO STRUCTURE
	ti.cbSize = sizeof(TOOLINFO);
	ti.uFlags = TTF_SUBCLASS;
	ti.hwnd = m_hUnskinButton;
	ti.hinst = m_hInstance;
	ti.uId = uid;
	ti.lpszText = lptstr;
	// ToolTip control will cover the whole window
	ti.rect.left = rect.left;    
	ti.rect.top = rect.top;
	ti.rect.right = rect.right;
	ti.rect.bottom = rect.bottom;

	// Activate the unskin button tooltip
	SendMessage(m_hUnskinButtonTT, TTM_ADDTOOL, 0, (LPARAM) (LPTOOLINFO) &ti);

}

///////////////////////////////////////////////
// PortScannerWindow::WinProc
///////////////////////////////////////////////

LRESULT CALLBACK PortScannerWindow::WinProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
	// Define our true window processor here

	switch(uMsg)
	{
		// If the user wants to close the application
	case WM_DESTROY:
		// then close it
		PostQuitMessage(WM_QUIT);
		break;
	case WM_COMMAND:
		switch(LOWORD(wParam)) {
	case ID_OUTPUT_SHOWOPEN:
	case IDB_SHOWOPENCHKBX:
		if (!m_bShowOpen) {
			CheckMenuItem(m_hMenu,ID_OUTPUT_SHOWOPEN,MF_CHECKED);
			SendMessage(m_hShowOpenCheckBx,BM_SETCHECK,BST_CHECKED,0);
			m_bShowOpen = TRUE;
		} else {
			CheckMenuItem(m_hMenu,ID_OUTPUT_SHOWOPEN,MF_UNCHECKED);
			SendMessage(m_hShowOpenCheckBx,BM_SETCHECK,BST_UNCHECKED,0);
			m_bShowOpen = FALSE;
		}
		break;
	case ID_OUTPUT_SHOWCLOSED:
	case IDB_SHOWCLOSEDCHKBX:
		if (!m_bShowClosed) {
			// Set menu item checked property
			CheckMenuItem(m_hMenu,ID_OUTPUT_SHOWCLOSED,MF_CHECKED);
			// Set check box to checked (for skinned mode)
			SendMessage(m_hShowClosedCheckBx,BM_SETCHECK,BST_CHECKED,0);
			// Set ShowClosed flag TRUE
			m_bShowClosed = TRUE;
		} else {
			// Set menu item unchecked property
			CheckMenuItem(m_hMenu,ID_OUTPUT_SHOWCLOSED,MF_UNCHECKED);
			// Set check box to unchecked (for skinned mode)
			SendMessage(m_hShowClosedCheckBx,BM_SETCHECK,BST_UNCHECKED,0);
			// Set ShowClosed flag FALSE
			m_bShowClosed = FALSE;
		}
		break;
	case ID_ABOUT_ABOUTPORTSCANNER:
		// About Dialogbox
		DialogBox(m_hInstance, MAKEINTRESOURCE(IDD_DIALOG1), m_hWnd, AboutDlgProc);
		break;
	case ID_APPEARANCE_SKINNEDMODE:
		if (m_bSkinned) {
			m_bSkinned = FALSE;
			Unskin();
		} else {
			m_bSkinned = TRUE;
			Regionize();
		}
		break;
	case ID_ACC_F4:
		SendMessage(m_hWnd, WM_COMMAND, (WPARAM)IDB_GOSCAN,0);
		break;
	case ID_ACC_ENTER:
		HWND testFocus;

		// get a handle to the window with focus
		testFocus = GetFocus();

		// pass WM_COMMAND to the SCAn button
		if ( (testFocus == m_hIPAddressEdit) || (testFocus == m_hStartPortEdit) || (testFocus == m_hEndPortEdit) || (testFocus == m_hGoButton)) {
			SendMessage(m_hWnd, WM_COMMAND, (WPARAM)IDB_GOSCAN,0);
		} else if (testFocus == m_hUnskinButton) {
			SendMessage(m_hWnd, WM_COMMAND, (WPARAM)IDB_UNSKIN,0);
		} else if (testFocus == m_hCloseButton) {
			SendMessage(m_hWnd, WM_COMMAND, (WPARAM)IDB_CLOSEWINDOW,0);
		} else if (testFocus == m_hDisplayArea) {
			SendMessage(m_hDisplayArea, EM_REPLACESEL,0,(LPARAM)(LPSTR)"\r\n");
		} else {
			return DefWindowProc(hWnd, uMsg, wParam, lParam);
		}
		break;
	case IDB_GOSCAN:
		if (!m_bScanFlag) {
			if (validateInput()) {
				DWORD dwThreadParam = (DWORD)this;
				DWORD dwThreadID;
				m_hThread = CreateThread (NULL, 0, ThreadProc, (VOID *)this, 0, &dwThreadID);
			}
			break;
		} else {
			TerminateThread(m_hThread, 0);
			m_bScanFlag=FALSE;
			SetDlgItemText(m_hWnd, IDB_GOSCAN, "SCAN");
			break;
		}
		break;
	case IDB_CLOSEWINDOW:
		PostQuitMessage(0);
		break;
	case IDB_UNSKIN:
		if (m_bSkinned) Unskin();
		break;
		}
		break;
	case WM_PAINT:

		PAINTSTRUCT ps;
		BeginPaint(m_hWnd,&ps);
		if (m_bSkinned) Skin(ps.hdc);
		SetBkMode(ps.hdc,TRANSPARENT);
		SetTextColor(ps.hdc, RGB(50,50,50));

		// Display labels for edit boxes
		TextOut(ps.hdc, 30,  45, "IP Address",10);
		TextOut(ps.hdc, 160, 45, "Start Port",10);
		TextOut(ps.hdc, 270, 45, "End Port",  8 );

		// Display labels for check boxes, if in skinned mode
		if (m_bSkinned) {
			TextOut(ps.hdc, 12, 470, "Show: open", 10);
			TextOut(ps.hdc, 120, 470, "closed", 6);
			EndPaint(m_hWnd,&ps);
		}
		break;
	case WM_LBUTTONDOWN:
		SendMessage(hWnd, WM_NCLBUTTONDOWN, HTCAPTION, NULL);
		break;
	default:
		// Process the left-over messages
		return DefWindowProc(hWnd, uMsg, wParam, lParam);
	}

	// If something was not done, let it go
	return 0;
}

///////////////////////////////////////////////
// PortScannerWindow::GrabTextFromEdit
///////////////////////////////////////////////

char* PortScannerWindow::GrabTextFromEdit(int nResourceID) {

	int len = GetWindowTextLength(GetDlgItem(m_hWnd, nResourceID));
	if (len > 0) {
		char *buffer;
		buffer = (char*)GlobalAlloc(GPTR, len + 1);
		GetDlgItemText(m_hWnd, nResourceID, buffer, len + 1);

		return buffer;
	}
}

///////////////////////////////////////////////
// PortScannerWindow::validateInput
///////////////////////////////////////////////

BOOL PortScannerWindow::validateInput(){
	// Validate ip address (implement later)

	BOOL bSuccess;
	if (GetDlgItemInt(m_hWnd, IDE_STARTPORT, &bSuccess, FALSE) >= 1)
		if(GetDlgItemInt(m_hWnd, IDE_ENDPORT, &bSuccess, FALSE) >= 1)
			if (GetDlgItemInt(m_hWnd, IDE_STARTPORT, &bSuccess, FALSE) <= GetDlgItemInt(m_hWnd, IDE_ENDPORT, &bSuccess, FALSE))
				return TRUE;

	MessageBox(m_hWnd, "Invalid Entry,\nPlease re-enter information", "Invalid Data Entered", 
		MB_OK | MB_ICONEXCLAMATION);
	return FALSE;
}


///////////////////////////////////////////////
// PortScannerWindow::goScan
///////////////////////////////////////////////

BOOL PortScannerWindow::goScan() {

	SOCKET lhSocket;		// Our socket
	SOCKADDR_IN lSockAddr;	// The SOCKADDR_IN structure containing IP and port info
	WSADATA wsaData;		// WinSock config data structure

	int		lConnect;		// Connection status flag

	int		StartPort;
	int		EndPort;
	char*	IPAddress;
	char*	IPResolved;
	BOOL	bSuccess;		// Success flag needed for GetDlgItemInt

	char*	buffer;			// Buffer to hold updated info for the text output area
	int		nTxtLen;

	// Get the IP Address, Start Port and End Port
	// We have already validated the input
	IPAddress = GrabTextFromEdit(IDE_IPADDRESS);
	StartPort = GetDlgItemInt(m_hWnd, IDE_STARTPORT,&bSuccess,FALSE);
	EndPort = GetDlgItemInt(m_hWnd, IDE_ENDPORT,&bSuccess,FALSE);

	// Check if we have a name or an IP
	int isIP = 1;
	int i;

	for(i=0; i < strlen(IPAddress); i++) {
		if( IPAddress[i] == '.') continue;
		else if( isalpha(IPAddress[i]) ) {
			isIP = 0;
			break;
		}
	}

	// ResolveDNS if we have a name
	if (!isIP) IPResolved = ResolveDNS(IPAddress);
	else IPResolved = IPAddress;

	// Bail out if resolution failed
	if (IPResolved == NULL) return FALSE;

	// Initialize WinSock
	if(WSAStartup(MAKEWORD(2,0),&wsaData) != 0) {
		MessageBox(m_hWnd, "Socket Initialization Error.", "Socket Error", MB_OK | MB_ICONEXCLAMATION);
		return false;
	}

	// Allocate space for text output
	buffer = (char*)malloc(100*sizeof(char));

	// Loop through from StartPort to EndPort
	for (int i=StartPort;i<=EndPort;i++) {

		// Initialize Socket
		lhSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
		if(lhSocket == INVALID_SOCKET) {
			MessageBox(m_hWnd, "Invalid Socket.", "Socket Error", MB_OK | MB_ICONEXCLAMATION);
		}

		// Zero out SOCKADDR_IN structure
		memset(&lSockAddr,0, sizeof(lSockAddr));

		// Fill SOCKADDR_IN structure
		lSockAddr.sin_family = AF_INET;
		lSockAddr.sin_port = htons(i);
		lSockAddr.sin_addr.s_addr = inet_addr(IPResolved);

		// Attempt connect
		lConnect = connect(lhSocket,(SOCKADDR *)&lSockAddr,sizeof(SOCKADDR_IN));

		if(lConnect != 0){
			// On Connect failure:
			// Grab text from text area, and output result of this scan
			if (m_bShowClosed) {
				sprintf(buffer,"%s:%d - Closed\r\n",IPAddress,i);
				nTxtLen = GetWindowTextLength(GetDlgItem(m_hWnd,IDT_OUTPUT));
				SendMessage(GetDlgItem(m_hWnd,IDT_OUTPUT), EM_SETSEL, nTxtLen, nTxtLen);		// move caret to end
				SendMessage(GetDlgItem(m_hWnd,IDT_OUTPUT), EM_REPLACESEL, 0, (LPARAM)buffer);	// append text
				SendMessage(GetDlgItem(m_hWnd,IDT_OUTPUT), EM_SCROLLCARET, 0, 0);				// scroll to caret
			}
		} else {
			// On connect success
			if(m_bShowOpen){
				sprintf(buffer,"%s:%d - Open\r\n",IPAddress,i);
				SendMessage(GetDlgItem(m_hWnd,IDT_OUTPUT), EM_SETSEL, -1, -1);					// move caret to end
				SendMessage(GetDlgItem(m_hWnd,IDT_OUTPUT), EM_REPLACESEL, 0, (LPARAM)buffer);	// append text
				SendMessage(GetDlgItem(m_hWnd,IDT_OUTPUT), EM_SCROLLCARET, 0, 0);				// scroll to caret
			}
		}
		closesocket(lhSocket);
	}
	
	WSACleanup();
	return TRUE;
}

///////////////////////////////////////////////
// PortScannerWindow::Regionize
///////////////////////////////////////////////
BOOL PortScannerWindow::Regionize() {
	// Remove title bar and prevent resizing
	DWORD dwStyle = GetWindowLong(m_hWnd, GWL_STYLE);
	dwStyle &= ~(WS_CAPTION|WS_SIZEBOX);
	SetWindowLong(m_hWnd, GWL_STYLE, dwStyle);

	// Hide the menu
	SetMenu(m_hWnd,NULL);

	// Define and set the region
	HRGN hRegion = CreateRectRgn(0 ,0, m_pRect->right-m_pRect->left, m_pRect->bottom-m_pRect->top);

	SetWindowRgn(m_hWnd, hRegion, true);

	DeleteObject(hRegion);

	m_bSkinned = TRUE;

	// show the unskin button
	dwStyle = GetWindowLong(GetDlgItem(m_hWnd,IDB_UNSKIN),GWL_STYLE);
	dwStyle |= WS_VISIBLE;
	SetWindowLong(GetDlgItem(m_hWnd,IDB_UNSKIN),GWL_STYLE, dwStyle);

	// show the close button
	dwStyle = GetWindowLong(GetDlgItem(m_hWnd,IDB_CLOSEWINDOW),GWL_STYLE);
	dwStyle |= WS_VISIBLE;
	SetWindowLong(GetDlgItem(m_hWnd,IDB_CLOSEWINDOW), GWL_STYLE, dwStyle);

	// show the check boxes
	dwStyle = GetWindowLong(GetDlgItem(m_hWnd,IDB_SHOWOPENCHKBX),GWL_STYLE);
	dwStyle |= WS_VISIBLE;
	SetWindowLong(GetDlgItem(m_hWnd,IDB_SHOWOPENCHKBX), GWL_STYLE, dwStyle);

	dwStyle = GetWindowLong(GetDlgItem(m_hWnd,IDB_SHOWCLOSEDCHKBX),GWL_STYLE);
	dwStyle |= WS_VISIBLE;
	SetWindowLong(GetDlgItem(m_hWnd,IDB_SHOWCLOSEDCHKBX), GWL_STYLE, dwStyle);

	// hide the group boxes
	dwStyle = GetWindowLong(GetDlgItem(m_hWnd,IDB_OUTPUTGROUP),GWL_STYLE);
	dwStyle &= ~(WS_VISIBLE);
	SetWindowLong(GetDlgItem(m_hWnd,IDB_OUTPUTGROUP), GWL_STYLE, dwStyle);

	dwStyle = GetWindowLong(GetDlgItem(m_hWnd,IDB_SETTINGSGROUP),GWL_STYLE);
	dwStyle &= ~(WS_VISIBLE);
	SetWindowLong(GetDlgItem(m_hWnd,IDB_SETTINGSGROUP), GWL_STYLE, dwStyle);

	// Make the output box a bit smaller to compensate for the Glowdot logo
	SetWindowPos(m_hDisplayArea,NULL,17,107,463,306,SWP_NOZORDER);

	InvalidateRect(m_hWnd, NULL, TRUE);
	SetWindowPos(m_hWnd, NULL, 0,0,500,500, SWP_NOMOVE|SWP_NOZORDER);

	return TRUE;
}

///////////////////////////////////////////////
// PortScannerWindow::Skin()
///////////////////////////////////////////////
BOOL PortScannerWindow::Skin(HDC dc) {

	// load the skin bitmap from resource
	HBITMAP hSkinBmp = LoadBitmap(m_hInstance, MAKEINTRESOURCE(IDB_BITMAP1));
	if (!hSkinBmp) return -1;

	// create a device context for the skin
	HDC dcSkin = CreateCompatibleDC(0);

	// select the skin bitmap
	HBITMAP hOldBmp = (HBITMAP)SelectObject(dcSkin, hSkinBmp);

	BitBlt(dc, 0,0,m_pRect->right-m_pRect->left,m_pRect->bottom-m_pRect->top, dcSkin, 0,0, SRCCOPY);

	m_bSkinned = TRUE;	

}
///////////////////////////////////////////////
// PortScannerWindow::Unskin()
///////////////////////////////////////////////
BOOL PortScannerWindow::Unskin(){

	// unassign the region
	SetWindowRgn(m_hWnd, NULL, false);

	DWORD dwStyle;

	// change window style (show caption bar again)
	dwStyle = GetWindowLong(m_hWnd, GWL_STYLE);
	dwStyle |= WS_CAPTION | WS_SIZEBOX;
	SetWindowLong(m_hWnd, GWL_STYLE, dwStyle);

	// Show the menu
	SetMenu(m_hWnd,m_hMenu);

	// hide the unskin button
	dwStyle = GetWindowLong(GetDlgItem(m_hWnd,IDB_UNSKIN),GWL_STYLE);
	dwStyle &= ~(WS_VISIBLE);
	SetWindowLong(GetDlgItem(m_hWnd,IDB_UNSKIN), GWL_STYLE, dwStyle);

	// hide the close button
	dwStyle = GetWindowLong(GetDlgItem(m_hWnd,IDB_CLOSEWINDOW),GWL_STYLE);
	dwStyle &= ~(WS_VISIBLE);
	SetWindowLong(GetDlgItem(m_hWnd,IDB_CLOSEWINDOW), GWL_STYLE, dwStyle);

	// hide the check boxes
	dwStyle = GetWindowLong(GetDlgItem(m_hWnd,IDB_SHOWOPENCHKBX),GWL_STYLE);
	dwStyle &= ~(WS_VISIBLE);
	SetWindowLong(GetDlgItem(m_hWnd,IDB_SHOWOPENCHKBX), GWL_STYLE, dwStyle);

	dwStyle = GetWindowLong(GetDlgItem(m_hWnd,IDB_SHOWCLOSEDCHKBX),GWL_STYLE);
	dwStyle &= ~(WS_VISIBLE);
	SetWindowLong(GetDlgItem(m_hWnd,IDB_SHOWCLOSEDCHKBX), GWL_STYLE, dwStyle);

	// show the group boxes
	dwStyle = GetWindowLong(GetDlgItem(m_hWnd,IDB_OUTPUTGROUP),GWL_STYLE);
	dwStyle |= WS_VISIBLE;
	SetWindowLong(GetDlgItem(m_hWnd,IDB_OUTPUTGROUP), GWL_STYLE, dwStyle);

	dwStyle = GetWindowLong(GetDlgItem(m_hWnd,IDB_SETTINGSGROUP),GWL_STYLE);
	dwStyle |= WS_VISIBLE;
	SetWindowLong(GetDlgItem(m_hWnd,IDB_SETTINGSGROUP), GWL_STYLE, dwStyle);

	// Restore the display box to its normal size
	SetWindowPos(m_hDisplayArea,NULL,10,100, 470, 340, SWP_NOZORDER);

	// flag just to make sure our app knows we unskinned
	m_bSkinned = FALSE;

	// force a window repainting
	InvalidateRect(m_hWnd, NULL, TRUE);
	SetWindowPos(m_hWnd, NULL, 0, 0, 1, 1, SWP_NOMOVE|SWP_NOZORDER);
	SetWindowPos(m_hWnd, NULL, 0, 0, m_pRect->right-m_pRect->left,m_pRect->bottom-m_pRect->top, SWP_NOMOVE|SWP_NOZORDER);

	return TRUE;
}

///////////////////////////////////////////////
// PortScannerWindow::ThreadProc()
///////////////////////////////////////////////

DWORD PortScannerWindow::ThreadProc(LPVOID pvoid) {

	// Change the text of the IDB_GOSCAN button to STOP
	SetDlgItemText(((PortScannerWindow *)pvoid)->m_hWnd, IDB_GOSCAN,"STOP");

	// Set the flag to true
	((PortScannerWindow *)pvoid)->m_bScanFlag = TRUE;

	// Do the Scan
	((PortScannerWindow *)pvoid)->goScan();

	// Set the flag false
	((PortScannerWindow *)pvoid)->m_bScanFlag = FALSE;

	// Change the text back
	SetDlgItemText(((PortScannerWindow *)pvoid)->m_hWnd, IDB_GOSCAN, "SCAN");

	return (DWORD)1;
}

///////////////////////////////////////////////
// PortScannerWindow::ResolveDNS
///////////////////////////////////////////////

char* PortScannerWindow::ResolveDNS(char *unresolvedIP) {

	WORD sockVersion;
	WSADATA wsaData;
	int nret;
	char *IPResolved = "";
	char *buffer;

	sockVersion = MAKEWORD(2,0);

	// Initialize Winsock as before
	WSAStartup(sockVersion,&wsaData);

	// pointer to the hostent structure
	LPHOSTENT Host;

	Host = gethostbyname(unresolvedIP);

	if (!Host) {
		// Output error message
		buffer = (char*)malloc(100*sizeof(char));

		sprintf(buffer,"Resolving %s:\r\nName resolution failed for %s.\r\n\r\n",unresolvedIP,unresolvedIP);

		int nTxtlen = GetWindowTextLength(GetDlgItem(m_hWnd,IDT_OUTPUT));

		SendMessage(GetDlgItem(m_hWnd,IDT_OUTPUT), EM_SETSEL, nTxtlen, nTxtlen);		//move caret to end
		SendMessage(GetDlgItem(m_hWnd,IDT_OUTPUT), EM_REPLACESEL, 0, (LPARAM)buffer);	//append text
		SendMessage(GetDlgItem(m_hWnd,IDT_OUTPUT), EM_SCROLLCARET, 0, 0);				//scroll to caret

		WSACleanup();

		return NULL;
	}
	else {
		// Set IPResolved to the IP address returned by gethostbyname
		struct in_addr *address = (struct in_addr *) Host->h_addr_list[0];
		IPResolved = inet_ntoa(*address);

		// output message stating that resolution was performed and successful
		buffer = (char*)malloc(100*sizeof(char));

		sprintf(buffer, "Resolving %s:\r\n%s resolves to %s.\r\n\r\n",unresolvedIP,unresolvedIP,IPResolved);

		int nTxtlen = GetWindowTextLength(GetDlgItem(m_hWnd,IDT_OUTPUT));

		SendMessage(GetDlgItem(m_hWnd,IDT_OUTPUT), EM_SETSEL, nTxtlen, nTxtlen);		//move caret to end
		SendMessage(GetDlgItem(m_hWnd,IDT_OUTPUT), EM_REPLACESEL, 0, (LPARAM)buffer);	//append text
		SendMessage(GetDlgItem(m_hWnd,IDT_OUTPUT), EM_SCROLLCARET, 0, 0);				//scroll to caret
	}
	return IPResolved;

	WSACleanup();
}